package com.seleniti.enpareja.web.desktop.client.ui.widget;

import org.ioc.commons.impl.gwt.client.ui.DisplayComposite;
import org.ioc.commons.ui.HasValue;
import org.ioc.commons.ui.IsWidget;
import org.ioc.commons.ui.features.Info;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
import com.google.gwt.resources.client.CssResource.Shared;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.client.HasSafeHtml;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Widget which show useful information on screen about the result of an
 * operation. It can show 4 type of messages:
 * <ul>
 * <li>WARNING</li>
 * <li>OPERATION_OK</li>
 * <li>INFO</li>
 * <li>ERROR</li>
 * </ul>
 * 
 * @author EPTISA-TI
 * 
 */
public class InfoInlineWidget extends Composite implements HasHTML, HasSafeHtml, Info, HasClickHandlers, IsWidget {

	private static InfoInlineUiBinder uiBinder = GWT.create(InfoInlineUiBinder.class);

	interface InfoInlineUiBinder extends UiBinder<Widget, InfoInlineWidget> {
	}

	private boolean autoDisplay = true;

	@ImportedWithPrefix("infoInline")
	@Shared
	public static interface Style extends CssResource {
		String box();

		String text();

		String warning();

		String operationOk();

		String info();

		String error();
	}

	private InfoType type = InfoType.WARNING;

	@UiField
	HorizontalPanel panel;

	@UiField
	HTML txt;

	@UiField
	Panel content;

	@UiField
	Style css;

	@UiField
	Image icon;

	@UiField
	ImageResource exclamationIcon;

	@UiField
	ImageResource tickIcon;

	@UiField
	ImageResource infoIcon;

	@UiField
	ImageResource errorIcon;

	private HasValue<String> message;

	public InfoInlineWidget() {
		initWidget(uiBinder.createAndBindUi(this));
		DOM.sinkEvents(this.getElement(), Event.ONCLICK);
	}

	public InfoInlineWidget(String text, InfoType type) {
		this();
		this.setText(text);
		this.setType(type);
	}

	public String getText() {
		return txt.getText();
	}

	public void setText(String text) {
		txt.setText(text);
		if (autoDisplay) {
			panel.setVisible(text != null && text.length() > 0);
		}
	}

	public String getHTML() {
		return txt.getHTML();
	}

	public void setHTML(String html) {
		txt.setHTML(html);
		if (autoDisplay) {
			panel.setVisible(html != null && html.length() > 0);
		}
	}

	@Override
	public void setHTML(SafeHtml html) {
		txt.setHTML(html);
		if (autoDisplay) {
			panel.setVisible(html != null && html.asString().length() > 0);
		}
	}

	@Override
	public void setHeight(String height) {
		panel.setHeight(height);
	}

	@Override
	public void setWidth(String width) {
		panel.setWidth(width);
	}

	public InfoType getType() {
		return type;
	}

	public void setType(InfoType type) {
		switch (this.type) {
		case WARNING:
			panel.removeStyleName(css.warning());
			txt.removeStyleName(css.warning());
			break;
		case OPERATION_OK:
			panel.removeStyleName(css.operationOk());
			txt.removeStyleName(css.operationOk());
			break;
		case INFO:
			panel.removeStyleName(css.info());
			txt.removeStyleName(css.info());
			break;
		case ERROR:
			panel.removeStyleName(css.error());
			txt.removeStyleName(css.error());
			break;
		}

		this.type = type;

		switch (type) {
		case WARNING:
			panel.addStyleName(css.warning());
			txt.addStyleName(css.warning());
			icon.setResource(exclamationIcon);
			break;
		case OPERATION_OK:
			panel.addStyleName(css.operationOk());
			txt.addStyleName(css.operationOk());
			icon.setResource(tickIcon);
			break;
		case INFO:
			panel.addStyleName(css.info());
			txt.addStyleName(css.info());
			icon.setResource(infoIcon);
			break;
		case ERROR:
			panel.addStyleName(css.error());
			txt.addStyleName(css.error());
			icon.setResource(errorIcon);
			break;
		}

		panel.addStyleName(css.box());
	}

	public HasValue<String> message() {
		if (this.message == null) {
			this.message = new HasValue<String>() {

				public void setValue(String text) {
					if (text != null) {
						InfoInlineWidget.this.setHTML(SafeHtmlUtils.fromSafeConstant(text));
					} else {
						InfoInlineWidget.this.setText(null);
					}
				}

				public String getValue() {
					return InfoInlineWidget.this.getText();
				}
			};
		}
		return this.message;
	}

	public void show() {
		setVisible(true);
	}

	public void hide() {
		setVisible(false);
	}

	@Override
	public boolean isVisible() {
		return panel.isVisible();
	}

	@Override
	public void setVisible(boolean visible) {
		panel.setVisible(visible);
	}

	public boolean isAutoDisplay() {
		return autoDisplay;
	}

	public void setAutoDisplay(boolean autoDisplay) {
		this.autoDisplay = autoDisplay;
	}

	public HandlerRegistration addClickHandler(ClickHandler handler) {
		return this.addHandler(handler, ClickEvent.getType());
	}

	@Override
	public IsWidget getWidgetParent() {
		return DisplayComposite.getWidgetParent(this);
	}

	@UiChild(tagname = "widget")
	public void addWidget(Widget w) {
		content.add(w);
	}
}
